﻿using System;
using TI_BLE_HCI_ClientLib.BaseEntities;

namespace TI_BLE_HCI_ClientLib.HCIBaseEntities
{
    public class HCICommand : BaseProtocolEntity
    {
        private byte _ogf;
        private ushort _ocf;

        private BaseEntityParameter[] _parameters = new BaseEntityParameter[0];

        public HCICommand()
        {
            base.PACKET_TYPE = 0x01;
        }

        public ushort Ocf
        {
            get { return _ocf; }
            set { _ocf = value; }
        }

        public byte Ogf
        {
            get { return _ogf; }
            set { _ogf = value; }
        }

        public BaseEntityParameter[] Parameters
        {
            get { return _parameters; }
            set { _parameters = value; }
        }

        public ushort OpCode
        {
            get
            {
                return (ushort)((_ogf << 10) + _ocf);
            }
        }

        protected void addParameters(BaseEntityParameter[] parsToAdd)
        {
            var newPars = new BaseEntityParameter[_parameters.Length + parsToAdd.Length];

            Array.Copy(_parameters, newPars, _parameters.Length);
            Array.Copy(parsToAdd, 0, newPars, _parameters.Length, parsToAdd.Length);

            _parameters = newPars;
        }

        public override byte[] ToByteArray()
        {
            var parSize = getParsSize();

            var arr = new byte[1 + 2 + 1 + parSize];

            arr[0] = this.PACKET_TYPE;
            arr[1] = (byte)(this.OpCode & 0xFF);
            arr[2] = (byte)(this.OpCode >> 8 & 0xFF);
            arr[3] = parSize;

            byte idx = 4;

            for (var i = 0; i < _parameters.Length; i++)
            {
                if (_parameters[i] is ByteParameter)
                {
                    arr[idx] = (_parameters[i] as ByteParameter).Value;
                    idx += 1;
                }
                else if (_parameters[i] is WordParameter)
                {
                    arr[idx] = (byte)((_parameters[i] as WordParameter).Value & 0xFF);
                    arr[idx + 1] = (byte)((_parameters[i] as WordParameter).Value >> 8 & 0xFF);
                    idx += 2;
                }
                else if (_parameters[i] is DoubleWordParameter)
                {
                    arr[idx] = (byte)((_parameters[i] as DoubleWordParameter).Value & 0xFF);
                    arr[idx + 1] = (byte)((_parameters[i] as DoubleWordParameter).Value >> 8 & 0xFF);
                    arr[idx + 2] = (byte)((_parameters[i] as DoubleWordParameter).Value >> 16 & 0xFF);
                    arr[idx + 3] = (byte)((_parameters[i] as DoubleWordParameter).Value >> 24 & 0xFF);
                    idx += 4;
                }
                else if (_parameters[i] is ByteArrayParameter)
                {
                    byte[] parArr = (_parameters[i] as ByteArrayParameter).Value;

                    Array.Copy(parArr, 0, arr, idx, parArr.Length);

                    idx += (byte)parArr.Length;
                }
            }

            return arr;
        }

        private byte getParsSize()
        {
            byte size = 0;

            for (var i = 0; i < _parameters.Length; i++)
            {
                if (_parameters[i] is ByteParameter)
                {
                    size += 1;
                }
                else if (_parameters[i] is WordParameter)
                {
                    size += 2;
                }
                else if (_parameters[i] is DoubleWordParameter)
                {
                    size += 4;
                }
                else if (_parameters[i] is ByteArrayParameter)
                {
                    size += (byte)((_parameters[i] as ByteArrayParameter).Value.Length);
                }
            }

            return size;
        }
    }
}